#ifndef _AVI_WRITER_H_
#define _AVI_WRITER_H_
/*!
 * \file 
 * AviWriter.h
 */

#include <vfw.h>

/*!
 * \brief Wrapping API associated with AVI file and stream
 *
 * This class is a wrapper class of API associated with AVI file and stream
 *
 *	This AVI wrapper supports the following:
 *	- Video Format: RGB32, RGB24, RGB16, YUY2, XVID, X264, MJPG
 *	- Audio Format: PCM, MULAW PCM, ALAW PCM
 *	- others: this AVI file can attach the third stream for an additional information
 *
 * - header file: AviWriter.h
 * - lib: util.lib
 * - DLL: util.dll
 */

class AFX_EXT_CLASS CAviWriter
{
public:

	/*!
	 * Enumerator of stream format supported in the class CAviWriter
	 */
	enum _TAG_STREAM_FORMAT 
	{
		FMT_RGB32 = 0,		/**< RGB 32bit 	*/
		FMT_RGB24,			/**< RGB 24bit */
		FMT_RGB16,			/**< RGB 16bit BBBB_BGGG_GGGR_RRRR 	*/
		FMT_YUY2,			/**< YUY2 Y0 U0 Y1 V0 	*/
		FMT_XVID,			/**< XVID (MPEG4) 	*/
		FMT_X264,			/**< X264 (H.264) 	*/
		FMT_MJPG			/**< MJPG (MJPEG)	*/
	};

	/*!
	 * Enumerator of audio format supported in the class CAviWriter
	 */
	enum _TAG_AUDIO_FORMAT
	{
		AFMT_PCM = 0,		/**< PCM 	*/
		AFMT_MULAW,			/**< MULAW PCM	*/
		AFMT_ALAW			/**< ALAW PCM 	*/
	};

public:
	CAviWriter();			/**< Contructor 	*/
	virtual ~CAviWriter();	/**< Desturctor 	*/

	/*!
	 * This function creates an AVI file and obtain the address of a file interface
	 *
	 * @param pcszFilePath Null-terminated string containing the name of the file to create
	 *
	 * @return if TRUE, the AVI file is successfully created.
	 */
	BOOL Open(LPCWSTR pcszFilePath);
	/*!
	 * Closes AVI file. All streams are also closed when they have been opened.
	 */
	VOID Close();

	/*!
	 * Creates a video stream
	 *
	 * @param iStreamFormat Video Format, it specifies at enum _TAG_STREAM_FORMAT
	 * @param dbFps Frame per second. type: DOUBLE
	 * @param iWidth Image width
	 * @param iHeight Image height
	 * @param iInitSample Sample number of the first frame of the AVI file.
	 * @param bSampleCountOutside if FALSE, sample count increases automatically by 1. Otherwise, sample count is set by a user.
	 *
	 * @return If TRUE, the video stream is successfully opened.
	 *
	 * @see _TAG_STREAM_FORMAT
	 */
	BOOL OpenVideoStream(INT iStreamFormat, DOUBLE dbFps, INT iWidth, INT iHeight, INT iInitSample = 0, BOOL bSampleCountOutside = FALSE);
	BOOL EditVideoStream(int nFrameRate);
	VOID CloseVideoStream();	/**< Close the video stream 	*/

	/*!
	 * Creates an audio stream
	 *
	 * @param iAudioFormat Audio Format, it specifies at enum _TAG_AUDIO_FORMAT
	 * @param iBitsPerSample Bits per sample, it should be equal to 8 or 16.
	 * @param iFrequency Sample Rate, in samples per second(hertz)
	 * @param iChannels Number of channels in the waveform-audio data. Monaural data uses one channel and stereo data uses two channels
	 * @param iSuggestedSize Recommended buffer size, in bytes, for the stream. Using the correct buffer size makes playback more efficient. 
	 * Use zero if you do not know the correct buffer size.
	 * 
	 * @return If TRUE, the audio stream is successfully opened.
	 *
	 * @see _TAG_AUDIO_FORMAT
	 */
	BOOL OpenAudioStream(INT iAudioFormat, INT iBitsPerSample, INT iFrequency, INT iChannels, INT iSuggestedSize);
	VOID CloseAudioStream();	/**< Close the audio stream 	*/

	BOOL IsOpen();		/**< Indicates whether AVI file is opened.	*/
	BOOL IsVideoOpen();	/**< Indicates whether the video stream is opened. 	*/
	BOOL IsAudioOpen();	/**< Indicates whether the audio stream is opened. 	*/

	/*!
	 * Writes data to a video stream
	 *
	 * @param pStream Pointer to a buffer containing the video data to write
	 * @param lStreamSize Size of the buffer referenced by pStream
	 * @param fKeyFrame Indicates this data does not rely on preceding data in the file
	 *
	 * @return Returns TRUE if successful or FALSE otherwise
	 */
	BOOL WriteVideo(BYTE *pStream, LONG lStreamSize, BOOL fKeyFrame);
	/*!
	 * Use the IncSampleCount function when a video stream has been opened with the parameter bSampleCountOutside as FALSE
	 *
	 * @param lInc Sample Count set by user.
	 */
	void IncSampleCount(LONG lInc);
	/*!
	 * Write data to a audio stream
	 *
	 * @param pAudioData Pointer to a buffer containing the audio date to write
	 * @param lAudioDataSize Size of the buffer referenced by pAudioData
	 *
	 * @return Returns TRUE if successful or FALSE otherwise
	 */
	BOOL WriteAudio(BYTE *pAudioData, LONG lAudioDataSize);

	//////////////////////////////////////////////////////////////////////////
	//not used anymore since 2012.08.20
	void SetExtraInfo(int nVidRes) { m_nVidRes = nVidRes; };
	int GetExtraInfo() { return m_nVidRes; }; 

	int GetWidth() { return m_nWidth; };
	int GetHeight() { return m_nHeight; };
	//////////////////////////////////////////////////////////////////////////


	//////////////////////////////////////////////////////////////////////////
	//User Stream
	/*!
	 * Creates a user stream
	 * In this application, it uses for saving extra information such as G-Sensor, GPS data, etc
	 *
	 * @param dbFps Frame per second. type: DOUBLE. This value usually sets the same as video FPS
	 * @param dwSuggestedBufferSize Recommended buffer size, in bytes, for the stream. Using the correct buffer size makes playback more efficient. 
	 * @param lpUserFormat Pointer to user format.
	 * @param dwUserFormatSize Size of the buffer referenced by lpUserFormat
	 *
	 * @return If TRUE, the user stream is successfully opened.
	 */
	BOOL OpenUserStream(DOUBLE dbFps, DWORD dwSuggestedBufferSize, LPVOID lpUserFormat, DWORD dwUserFormatSize);
	BOOL EditUserStream(int nFrameRate);
	VOID CloseUserStream();		/**< Close the user stream 	*/
	BOOL IsUserOpen();		/**< Indicates whether the user stream is opened. 	*/

	/*!
	 * Write data to a user stream
	 *
	 * @param pData Pointer to a buffer containing the user data to write
	 * @param lDataSize Size of the buffer referenced by pData
	 * @param bSync if bSync = TRUE, sample count is the same as video sample count which has been written just before.
	 * if FALSE, video sample count is the next count of video sample.
	 *
	 * @return Returns TRUE if successful or FALSE otherwise
	 */
	BOOL WriteUserData(BYTE *pData, LONG lDataSize, BOOL bSync = TRUE);

private:
	PAVIFILE m_pavFile;
	PAVISTREAM m_pavVideo;
	PAVISTREAM m_pavAudio;
	PAVISTREAM m_pavUser;

	LONG m_lStart;
	LONG m_lSamples;

	int m_nWidth;
	int m_nHeight;
	BOOL m_bSampleCountOutsize;

	LONG m_lAudioSamples;
	int m_nVidRes;

};

#endif